package com.jd.basic.service.impl;

import cn.hutool.core.util.StrUtil;
import com.jd.basic.exception.BusinessException;
import com.jd.basic.service.IVerifyCodeService;
import com.jd.basic.util.AjaxResult;
import com.jd.basic.util.StrUtils;
import com.jd.basic.util.VerifyCodeUtils;
import com.jd.user.domain.User;
import com.jd.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;
    @Override
    public AjaxResult verifyCodeImage(String key) { // 生成图片验证码
        // 生成随机验证码
        String imgCode = StrUtils.getComplexRandomString(4);
        // 通过key将验证码存入redis并设置过期时间
        redisTemplate.opsForValue().set(key, imgCode, 5, TimeUnit.MINUTES);
        // 将验证码转换图片并以base64进行编码
        String verifyCode = VerifyCodeUtils.verifyCode(115, 40, imgCode);
        return AjaxResult.me().setResultObj(verifyCode);
    }

    @Override
    public AjaxResult verifyCodePhone(Map<String, String> map) { // 生成手机验证码
        // 前端传递三个参数
        String phone = map.get("phone"); // 手机号
        String imageCode = map.get("imageCode"); // 图片验证码
        String imageCodeKey = map.get("imageCodeKey"); // redis存入图片验证码的key
        // 首先进行空值判断
        if (StrUtil.isBlank(phone) || StrUtil.isBlank(imageCode)
                || StrUtil.isBlank(imageCodeKey)) {
            throw new BusinessException("信息不能为空！");
        }
        // 图片验证码判断是否过期
        Object imgCodeObj = redisTemplate.opsForValue().get(imageCodeKey);
        if (imgCodeObj == null){
            throw new BusinessException("验证码已经过期！");
        }
        // 没有过期判断是否正确
        if (!imageCode.equalsIgnoreCase(imgCodeObj.toString())){
            throw new BusinessException("验证码输入错误！");
        }
        // 判断手机号是否被注册过
        User user = userMapper.findByPhone(phone);
        if (user != null){
            throw new BusinessException("该手机号已经被注册过！");
        }
        // 以上都成功开始生成手机验证码
        Object phoneCodeObj = redisTemplate.opsForValue().get("register:" + phone); // 根据key获取手机验证码
        // 首先判断是否已经有验证码
        String phoneCode = null;
        if (phoneCodeObj == null){ // 证明第一次获取或者过了过期时间
            phoneCode = StrUtils.getRandomString(4); // 生成手机验证码
        } else { // 存在验证码，判断是否过了重发时间，没过是违规操作
            Long oldTime = Long.parseLong(phoneCodeObj.toString().split(":")[1]); // 存储验证码时间
            Long nowTime = System.currentTimeMillis(); // 当前系统时间
            if (nowTime - oldTime < 60*1000){ // 没过重发时间
                throw new BusinessException("违规操作！请稍后重试！");
            } else {
            // 过了重发时间，存在验证码，将旧的验证码赋值给新的验证码
                phoneCode = phoneCodeObj.toString().split(":")[0];
            }
        }
        // 验证码有了存入redis并设置过期时间
        redisTemplate.opsForValue().set("register:" + phone,phoneCode + ":" + System.currentTimeMillis(),3,TimeUnit.MINUTES);
        // 调用短信接口发短信
//        SmsUtils.sendSms("17882296062","您的手机验证是:" + phoneCode + ",有效期为三分钟！");
        System.out.println("手机验证码:" + phoneCode);
        return new AjaxResult();
    }

    @Override
    public AjaxResult binderSmsCodePhone(Map<String, String> map) {
        //1.校验
        String phone = map.get("phone");
        //1.1.空值校验
        if (StrUtil.isBlank(phone)){ // 前端手机和图片验证码校验空值
            throw new BusinessException("手机号不能为空！");
        }
        //2.生成手机验证码
        //2.1.直接去redis根据key【register:phone】去获取
        Object PhoneCodeObj = redisTemplate.opsForValue().get("binder:" + phone);
        //a.如果没有【第一次发 or 过期了】：可以通过工具类或hutools生成手机验证码
        String phoneCode = null;
        if (PhoneCodeObj == null){
            phoneCode = StrUtils.getRandomString(4); // 不存在生成手机验证码
        } else { // 有 a.判断重发时间，一分钟
            Long oldTime = Long.parseLong(PhoneCodeObj.toString().split(":")[1]);
            Long nowTime = System.currentTimeMillis(); //
            if (nowTime - oldTime < 60*1000){  //b.redis保存的时间戳与当前系统的时间戳相减
                //b1.如果没有过重发时间【不能请求这个业务】，请求了就是违规操作 - 抛异常
                throw new BusinessException("违规操作！请稍后重试!");
            } else { //b2.如果过了重发时间【有效】，就使用以前的验证码
                phoneCode = PhoneCodeObj.toString().split(":")[0];
            }
        }
        //3.将手机短信验证码保存在redis，重新设置时间
        redisTemplate.opsForValue().set("binder:" + phone,phoneCode + ":"
                + System.currentTimeMillis(),3,TimeUnit.MINUTES);
        //4.调用SmsUtils工具类发送短信
//        SmsUtils.sendSms(phone,"您的手机验证是:" + phoneCode + ",有效期为三分钟！");
        System.out.println(phoneCode);
        return new AjaxResult();
    }

}
